﻿/************************************************************************
 * SMLib - State Model Library
 * Copyright (C) 2012-2013 Ali Khalili (khalili_DOT_ir_@SIGN_gmail_DOT_com)
 * **********************************************************************
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License (LGPL) published 
 * by the Free Software Foundation; either version 2.1 of the License, or (at your
 * option) any later version. This program is distributed without any
 * warranty. See the GNU Lesser General Public License for more details. 
 * ***********************************************************************
 * File         :     SMLib\Interoperability\DOT\DotHelper_DFA.cs
 * Description  :     DOT format helper for DFAs
 * Change log   :     -1 Sep 2013:  Initial Version
 * To Do        :     
 ************************************************************************/
using System;
using System.Collections.Generic;
using SMLib.Automata.Base;
using SMLib.Automata.DFA;

namespace SMLib.Interoperability.DOT
{
	/// <summary>
	/// DOT Helper for importing/exporting DFAs
	/// </summary>
	public class DotHelper_DFA :DotHelper<DFA.DFA_State,DFA.DFA_Transition>
	{
		public static void WriteToDot (string path, DFA dfa)
		{
			SMLib.Interoperability.DOT.DotHelper_DFA exporter = new SMLib.Interoperability.DOT.DotHelper_DFA ();
			(exporter as DotHelper<DFA.DFA_State,DFA.DFA_Transition>).WriteToDot (path, dfa);
		}

		/// <summary>
		/// Read a DFA from file.
		/// <remarks>Each line of the file should have the following pattern: "src" -&gt; "dst" : "label"</remarks>
		/// </summary>
		/// <param name="inputFile">full path of input file</param>
		public static DFA ReadFromDOT (string inputFile)
		{
			//string line;
			Alphabet Sigma = new Alphabet ();
			DFA myMachine = new DFA (Sigma);

			DotFormat dotReader = new DotFormat ();
			//string ilbl, olbl;
			foreach (DotFormat.DotTransition tr in dotReader.ReadDotFile(inputFile)) {
                   
				string src, dst, lbl;
				src = tr.Source;
				dst = tr.Destination;
				lbl = tr.Label;

				if (!Sigma.Contains (new StringSymbol (lbl)))
					Sigma.AddSymbol (new StringSymbol (lbl));

				DFA.DFA_State srcNode = null, dstNode = null;
				foreach (DFA.DFA_State n in myMachine.GetStates()) {
					if (((string)n.Identifier).Equals(src))
						srcNode = n;
					if (((string)n.Identifier).Equals(dst))
						dstNode = n;

					if (dstNode != null && srcNode != null)
						break;
				}
				if (srcNode == null) {
					srcNode = new DFA.DFA_State (src);
					myMachine.AddState (srcNode);
					if (src == dst)
						dstNode = srcNode;
				}
				
				
				if (dstNode == null) {
					dstNode = new DFA.DFA_State (dst);
					myMachine.AddState (dstNode);
				}
				DFA.DFA_Transition t = new DFA.DFA_Transition (new StringSymbol (lbl));
				t.SetDestination (dstNode);
				srcNode.Transitions.Add (t);
				//}
			}
			
			foreach (DFA.DFA_State state in myMachine.GetAllStates()) {
				if (state.Identifier.ToString ().StartsWith ("T"))
					state.isAccepting = true;
				else if (state.Identifier.ToString ().StartsWith ("F"))
					state.isAccepting = false;
				else
					throw new Exception ("State ID should starts with \"T\" or \"F\"");
			}
			return myMachine;
		}
	}
}
